package com.itheima.core.controller;


import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.common.dto.PageRequestDto;
import com.itheima.common.enums.HttpCodeEnum;
import com.itheima.common.vo.PageResultVo;
import com.itheima.common.vo.ResultVo;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

public abstract class AbstractCoreController<T> implements ICoreController<T> {
    /**
     * 获取日志对象
     */
    //有static修饰时，变量属于类变量，可以调用方法，不属于某个实例
    //没有static修饰时，变量叫成员变量，只属于某个对象
    private static final Logger logger = LoggerFactory.getLogger(AbstractCoreController.class);

    //定义调用方的service
    protected IService<T> coreService;

    public AbstractCoreController(IService<T> coreService) {
        this.coreService = coreService;
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @DeleteMapping("/del/{id}")
    @ApiOperation("通过id删除")
    @Override
    public ResultVo deleteById(@PathVariable Serializable id) {
        boolean result = coreService.removeById(id);
        if(result){
            return ResultVo.ok();
        }
        return ResultVo.error();
    }

    /**
     * 新增数据
     *
     * @param record
     * @return
     */
    @PostMapping("/save")
    @ApiOperation("新增")
    @Override
    public ResultVo<T> save(@RequestBody T record) {
        if(coreService.save(record)){
            return ResultVo.ok();
        }
        return ResultVo.error();
    }

    /**
     * 分页查询
     *
     * @param dto
     * @return
     */
    @PostMapping("/page")
    @ApiOperation("分页查询")
    @Override
    public PageResultVo findByPage(@RequestBody PageRequestDto dto) {
        IPage<T> pageParams = new Page<>(dto.getPage(), dto.getSize());
        IPage<T> pageInfo = coreService.page(pageParams);

        return PageResultVo.pageResult(dto.getPage(),dto.getSize(),
                pageInfo.getTotal(),pageInfo.getRecords());
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("通过id查询")
    @Override
    public ResultVo<T> findById(@PathVariable Serializable id) {
        T t = coreService.getById(id);
        if(t != null){
            return ResultVo.ok(t);
        }
        return ResultVo.error();
    }

    /**
     * 查询所有
     *
     * @return
     */
    @GetMapping("/listAll")
    @ApiOperation("查询所有")
    @Override
    public ResultVo<List<T>> findAll() {
        List<T> list = coreService.list();
        if(list.size() > 0){
            return ResultVo.ok(list);
        }
        return ResultVo.error(HttpCodeEnum.DATA_NOT_EXIST);
    }

    /**
     * 通过条件查询
     *
     * @param record
     * @return
     */
    @GetMapping("/listCondition")
    @ApiOperation("根据条件查询")
    @Override
    public ResultVo<List<T>> findByCondition(T record) {
        QueryWrapper<T> queryWrapper = getWrapper(record, false);
        List<T> list = coreService.list(queryWrapper);
        return ResultVo.ok(list);
    }

    /**
     * 根据id更新
     *
     * @param record
     * @return
     */
    @PostMapping("/update")
    @ApiOperation("根据id更新")
    @Override
    public ResultVo updateById(@RequestBody T record) {
        boolean result = coreService.updateById(record);
        if(result){
            return ResultVo.ok();
        }
        return ResultVo.error();
    }

    public QueryWrapper<T> getWrapper(T condition, boolean stringAsLike) {
        //创建一个条件构造器
        QueryWrapper queryWrapper = new QueryWrapper();
        //判断条件是否为空
        if (condition == null) {
            return queryWrapper;
        }
        //获取该条件的字节码对象
        Class<?> aClass = condition.getClass();
        //得到该条件对象中的所有字段
        Field[] fields = aClass.getDeclaredFields();

        try {
            //遍历判断字段
            for (Field field : fields) {
                //判断，遇到id注解时，直接跳过
                if (field.isAnnotationPresent(TableId.class) ||
                        field.getName().equals("serialVersionUID")) {
                    continue;
                }

                //属性描述器
                PropertyDescriptor propertyDescriptor = BeanUtils.getPropertyDescriptor(aClass, field.getName());
                //先获取读方法的方法对象，再获取值

                Object value = propertyDescriptor.getReadMethod().invoke(condition);
                TableField annotation = field.getAnnotation(TableField.class);
                //判断传递值为空不做处理
                if(value != null){
                    //如果是字符串，则使用like模糊查询
                    if("java.lang.String".equals(value.getClass().getName()) && stringAsLike){
                        queryWrapper.like(annotation.value(),value);
                    }else{
                        //不是则使用精确查询
                        queryWrapper.eq(annotation.value(),value);
                    }
                }
            }
        } catch (IllegalAccessException | InvocationTargetException e) {
            logger.error("属性读取失败",e);
        }
        return queryWrapper;
    }
}
